package ws

import (
	"encoding/json"
	"log"
	"strings"

	"github.com/gorilla/websocket"
)

// 启动全局监听
func (m *clientManager) monitor() {
	for {
		select {
		case message := <-m.broadcast:
			m.check(message)
		case conn := <-m.register:
			m.clients.Store(conn, true)
			m.dynamic()
		case conn := <-m.unregister:
			conn.lock.Lock()

			conn.isClose = true

			m.clients.Delete(conn)
			_ = conn.socket.Close()
			close(conn.send)

			conn.lock.Unlock()

			m.dynamic()
		}
	}
}

// 检查接收数据中type的类型
func (m *clientManager) check(data []byte) {
	if rec := unmarshal(data); rec != nil {
		// 发送给组群中的所有人
		m.emit(rec)
	}
}

// 监控客户端动态
func (m *clientManager) dynamic() {
	m.onlineNum() // 在线数量
}

// 发送消息
func (m *clientManager) emit(rec *receiveMsg) {
	bm := newBroadcastMsg(rec.ToUser, rec.Data)
	switch rec.ContentType {
	case 4: // 30s 语音
		bm.MsgType = websocket.BinaryMessage
	default:
	}

	// 发送给指定类型
	switch {
	case rec.ToUser != "": // 一对一发送
		go m.forr(func(conn *client) (*broadcastMsg, bool) {
			return bm, isExist(bm.To, conn.uid)
		})
	case rec.GrpId != "": // 一对多广播
		go m.forr(func(conn *client) (*broadcastMsg, bool) {
			return bm, isExist(rec.GrpId, conn.grpId)
		})
	default: // ToUser and GrpId 都为空，向所有人发送
		go m.forr(func(conn *client) (*broadcastMsg, bool) {
			return bm, true
		})
	}
}

// 字符串按“,”分隔转数组
func StringToArr(from string) []string {
	from = strings.ReplaceAll(from, "，", ",")
	return strings.Split(from, ",")
}

// 字符中是否存在一个子字符串
func isExist(from, id string) (flag bool) {
	list := StringToArr(from)

	for _, uid := range list {
		if uid == id {
			flag = true
			break
		}
	}
	return
}

// 统计连接数量
func (m *clientManager) onlineNum() {
	// 后台接收数据,用于查看app平板的动态上下线
	var count int
	m.forr(func(conn *client) (*broadcastMsg, bool) {
		count++
		return nil, false
	})

	log.Printf("目前在线人数: %v\n", count)
}

// 解析数据
func unmarshal(data []byte) (rec *receiveMsg) {
	_ = json.Unmarshal(data, &rec)
	if rec.FromUser == "" || rec.Content == "" {
		return nil
	}

	rec.Data = data
	return
}

// 默认设置属性
func newBroadcastMsg(to string, msg []byte) *broadcastMsg {
	return &broadcastMsg{To: to, Msg: msg, MsgType: websocket.TextMessage}
}

// 遍历连接
func (m *clientManager) forr(callback func(conn *client) (*broadcastMsg, bool)) {
	m.clients.Range(func(k, v interface{}) bool {
		if conn, ok := k.(*client); ok {
			if broadcastMsg, ok := callback(conn); ok {
				conn.lock.RLock()
				if !conn.isClose {
					conn.send <- broadcastMsg
				}
				conn.lock.RUnlock()
			}
		}
		return true
	})

}
